home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
tuner
/
tuner_io.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
8KB
|
348 lines
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/stat.h>
#ifndef INADDR_NONE
#define INADDR_NONE -1
#endif
#include "tuner.h"
static do_stationcall();
char *dft_nets[] = { DFT_NETS, 0 };
char radio_host[64]; /* Host where radio runs */
int transmitter_port = CTLPRT_XMIT; /* Default control port for transmitters */
int radio_port = CTLPRT_RADIO; /* Default control port for radios */
struct sockaddr_in radio_addr; /* Address of our radio */
struct sockaddr_in bcast_addrs[MAXNET]; /* Addresses of transmitters */
int num_bcast_addrs = 0;
struct station_info {
char name[MAXNAME]; /* station name */
int port; /* UDP broadcast port */
int is_playing; /* 1 if currently transmitting */
char logfile[MAXNAME]; /* Name of cdlog file */
int since; /* Play time in minutes of current CD */
char cdname[MAXNAME]; /* Current CD name */
};
struct station_info stations[MAXSTATION];
char *station_names[MAXSTATION]; /* Hack. Points into stations array */
int num_stations;
char cur_name[MAXNAME];
char cur_play[MAXNAME];
char cur_time[MAXNAME];
int cur_mute;
int cur_port;
int origtune = -1;
int sock; /* Our socket */
int sc_sock; /* Stationcall socket */
char plbuf[MAXPLBUF][MAXNAME];
char *playlist[MAXPLBUF];
int num_playlist;
init_io() {
struct hostent *hent;
int i;
for( i=0; i<MAXSTATION; i++)
station_names[i] = stations[i].name;
/*XXX Process args */
sock = opensock();
sc_sock = openscsock();
/*
** Divine address struct for radio station we're controlling.
*/
if ( radio_host[0] == 0 ) {
if ( gethostname(radio_host, sizeof(radio_host)) < 0 ) {
perror("gethostname");
exit(1);
}
}
if ( (hent=gethostbyname(radio_host)) == 0 ) {
#ifndef sun
herror(radio_host);
#else
fprintf(stderr, "%s: Unknown host name\n", radio_host);
#endif
exit(1);
}
radio_addr.sin_family = AF_INET;
radio_addr.sin_port = htons(radio_port);
memcpy(&radio_addr.sin_addr, hent->h_addr, hent->h_length);
/*
** Create list of broadcast addresses for locating stations.
*/
if ( num_bcast_addrs == 0 ) {
/*
** No addresses in arguments. Do the defaults.
*/
char **p;
for( p=dft_nets; *p; p++ )
add_bcast_addr(*p);
}
/*
** Obtain station info and current station.
*/
get_stations();
get_curinfo();
origstation = cur_tune;
show_tuner(station_names, num_stations);
show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
show_playlist(playlist, num_playlist,1);
watch_socket(sc_sock, do_stationcall);
}
get_stations() {
int i;
char *s;
struct station_info *p;
/*
** Clear old stations.
*/
num_stations = 0;
/*
** Broadcast info request.
*/
for(i=0; i<num_bcast_addrs; i++)
sendsock(sock, &bcast_addrs[i], "radio:s");
/*
** Receive replies.
*/
while ( (s=recvsock(sock)) ) {
p = stations + num_stations;
if ( parse_stationcall(p, s) )
num_stations++;
}
}
static
do_stationcall(d1, d2, d3)
int d1, d2, d3;
{
char *s;
struct station_info sistr;
int i;
if ( (s=recvsock(sc_sock)) == NULL ) {
fprintf(stderr, "tuner: stationcall event without data?\n");
return;
}
if ( !parse_stationcall(&sistr, s) )
return;
for ( i=0; i<num_stations; i++)
if ( stations[i].port == sistr.port ) {
stations[i] = sistr;
if ( sistr.port == cur_port ) {
if( get_curinfo() )
show_playlist(playlist, num_playlist,1);
show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
}
return;
}
stations[num_stations] = sistr;
num_stations++;
show_tuner(station_names, num_stations);
}
parse_stationcall(p, s)
struct station_info *p;
char *s;
{
int port;
char name[MAXNAME], logname[MAXNAME], cdname[MAXNAME];
int is_playing, since;
int i;
is_playing = 1;
since = -1;
cdname[0] = '\0';
logname[0] = '\0';
i = sscanf(s, "radio:S:%[^:]:%d:%d:%[^:]:%d:%[^\n]", name, &port,
&is_playing, logname, &since, cdname);
if ( i >= 2 ) {
strncpy(p->name, name, MAXNAME);
p->port = port;
p->is_playing = is_playing;
strncpy(p->logfile, logname, MAXNAME);
p->since = since;
strncpy(p->cdname, cdname, MAXNAME);
return 1;
}
fprintf(stderr, "Ill-formatted station call(%d): '%s'\n",i, s);
return 0;
}
add_bcast_addr(addr)
char *addr;
{
struct sockaddr_in *sp;
unsigned long iaddr;
sp = &bcast_addrs[num_bcast_addrs++];
if ( (iaddr=inet_addr(addr)) == INADDR_NONE) {
fprintf(stderr, "Ill-formatted address %s\n", addr);
exit(1);
}
sp->sin_family = AF_INET;
sp->sin_addr.s_addr = iaddr;
sp->sin_port = htons(transmitter_port);
}
get_curinfo() {
char *s;
int n;
int port, muteoff;
int i;
FILE *fp;
char buf[128];
int t;
sendsock(sock, &radio_addr, "radio:i");
num_playlist = 0;
if ( s = recvsock(sock) ) {
/*
** Parsing is funny, because older radio programs didn't have the
** mute feature (so only send a single number, the port).
*/
n = sscanf(s, "radio:I:%d:%d", &muteoff, &port);
if ( n == 0 ) {
fprintf(stderr, "Funny reply from radio program: %s\n", s);
return 1;
}
if ( n == 1 ) {
port = muteoff;
muteoff = 1;
}
cur_mute = !muteoff;
cur_port = port;
/*
** Try to find the corresponding station
*/
for(i=0; i<num_stations; i++) {
if ( cur_port == stations[i].port ) {
cur_tune = i+1;
strcpy(cur_name, stations[i].name);
strcpy(cur_play, stations[i].cdname);
t = stations[i].since / 60;
if ( t == 0 )
cur_time[0] = '\0';
else if ( t < 60 )
sprintf(cur_time, "%d minutes", t);
else
sprintf(cur_time, "%d hours", t/60);
if ( !stations[i].is_playing )
strcat(cur_time, "(Silent)");
if ( stations[i].logfile[0] )
return get_playlist(stations[i].logfile);
return 1;
}
}
if ( i == num_stations ) {
/* Couldn't find the station number */
cur_tune = 0;
sprintf(cur_name, "Unknown (port %d)", cur_port);
strcpy(cur_play, "?");
strcpy(cur_time, "?");
return 1;
}
}
fprintf(stderr, "Warning: radio program not responding\n");
strcpy(cur_name, "?");
strcpy(cur_time, "?");
strcpy(cur_play, "?");
cur_tune = 0;
return 1;
}
void
do_tune(station)
int station;
{
char buf[32];
if ( station == 0 ) return;
sprintf(buf, "radio:t:%d", stations[station-1].port);
sendsock(sock, &radio_addr, buf);
get_curinfo();
show_tune(cur_tune, cur_name, cur_play, cur_time, cur_mute);
show_playlist(playlist, num_playlist,1);
}
/*
** do_mute - Mute radio
*/
void
do_mute(onoff)
int onoff;
{
sendsock(sock, &radio_addr, onoff?"radio:0":"radio:1");
}
/*
** get last MAXPLBUF entries of playlist file.
*/
get_playlist(file)
char *file;
{
FILE *fp;
int i, j;
static char fnbuf[MAXNAME];
struct stat sb;
static int mtime, saved_num_playlist;
if ( strncmp(file, fnbuf, MAXNAME) == 0 ) {
if ( stat(file, &sb) >= 0 && sb.st_mtime == mtime ) {
/* Yes, cached copy still ok */
num_playlist = saved_num_playlist;
return 0;
}
}
if ( (fp=fopen(file, "r")) == 0 )
return;
strncpy(fnbuf, file, MAXNAME);
stat(file, &sb);
mtime = sb.st_mtime;
i = 0;
while( (fgets(plbuf[i%MAXPLBUF], MAXNAME, fp)) ) i++;
if ( i == 0 ) {
num_playlist = 0;
saved_num_playlist = 0;
return;
}
i--;
if ( i < MAXPLBUF ) {
num_playlist = i+1;
while ( i >= 0 ) {
playlist[i] = plbuf[i];
i--;
}
}
else {
for ( j=0; j<MAXPLBUF; j++) playlist[j] = plbuf[(i+j+1) % MAXPLBUF];
num_playlist = MAXPLBUF;
}
saved_num_playlist = num_playlist;
fclose(fp);
return 1;
}